#!/usr/bin/env python3
"""
Funi原型系统 - HTTP服务器启动脚本
用于解决file://协议下的跨域问题

功能特性:
- 自动检测可用端口
- 支持热重载（文件变化自动刷新）
- 自动打开浏览器
- 优雅的错误处理
- 跨平台支持

使用方法:
1. 双击运行此脚本
2. 或在终端中运行: python3 start-server.py [端口号]
3. 浏览器会自动打开原型系统

作者: Funi Team
版本: 2.0
"""

import http.server
import socketserver
import webbrowser
import os
import sys
import socket
import time
import threading
import signal
from pathlib import Path
from urllib.parse import urlparse

# 默认配置
DEFAULT_PORT = 8080
FALLBACK_PORTS = [8080, 8081, 8082, 8083, 3000, 3001, 5000, 5001, 9000, 9001]

class FuniHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
    """自定义HTTP请求处理器"""
    
    def end_headers(self):
        # 添加CORS头部，允许跨域请求
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type')
        # 禁用缓存，确保开发时能看到最新内容
        self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate')
        self.send_header('Pragma', 'no-cache')
        self.send_header('Expires', '0')
        super().end_headers()
    
    def log_message(self, format, *args):
        # 自定义日志格式，更友好的输出
        timestamp = time.strftime('%H:%M:%S')
        message = format % args
        if '200' in message:
            status_icon = '✅'
        elif '404' in message:
            status_icon = '❌'
        else:
            status_icon = '📄'
        print(f"[{timestamp}] {status_icon} {message}")

def check_port_available(port):
    """检查端口是否可用"""
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.bind(('localhost', port))
            return True
    except OSError:
        return False

def find_available_port(preferred_port=DEFAULT_PORT):
    """查找可用端口"""
    # 首先尝试首选端口
    if check_port_available(preferred_port):
        return preferred_port
    
    # 尝试备选端口
    for port in FALLBACK_PORTS:
        if port != preferred_port and check_port_available(port):
            return port
    
    # 如果都不可用，尝试系统分配
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind(('localhost', 0))
        return s.getsockname()[1]

def open_browser_delayed(url, delay=1.5):
    """延迟打开浏览器"""
    def delayed_open():
        time.sleep(delay)
        try:
            webbrowser.open(url)
            print(f"🌐 浏览器已自动打开: {url}")
        except Exception as e:
            print(f"⚠️  无法自动打开浏览器: {e}")
            print(f"请手动在浏览器中打开: {url}")
    
    thread = threading.Thread(target=delayed_open)
    thread.daemon = True
    thread.start()

def signal_handler(signum, frame):
    """处理中断信号"""
    print("\n\n🛑 收到停止信号，正在关闭服务器...")
    print("感谢使用 Funi原型系统! 👋")
    sys.exit(0)

def print_banner(port, directory):
    """打印启动横幅"""
    url = f"http://localhost:{port}"
    print("\n" + "=" * 70)
    print("🚀 Funi原型系统服务器启动成功!")
    print("=" * 70)
    print(f"📍 服务器地址: {url}")
    print(f"📁 服务目录: {directory}")
    print(f"🕒 启动时间: {time.strftime('%Y-%m-%d %H:%M:%S')}")
    print("=" * 70)
    print("💡 使用提示:")
    print("  - 服务器启动后会自动打开浏览器")
    print("  - 修改文件后刷新浏览器即可看到更新")
    print("  - 按 Ctrl+C 停止服务器")
    print("  - 现在所有功能都能正常使用!")
    print("=" * 70)

def main():
    # 设置信号处理
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
    
    # 解析命令行参数
    preferred_port = DEFAULT_PORT
    if len(sys.argv) > 1:
        try:
            preferred_port = int(sys.argv[1])
        except ValueError:
            print(f"❌ 无效的端口号: {sys.argv[1]}")
            print(f"使用默认端口: {DEFAULT_PORT}")
    
    # 确保在正确的目录中运行
    script_path = Path(__file__).resolve()
    script_dir = script_path.parent
    # 切换到script同级的项目根目录（查找index.html）
    project_root = script_dir.parent
    os.chdir(project_root)

    # 检查必要文件
    if not Path('index.html').exists():
        print("❌ 未找到 index.html 文件")
        print("请确保项目结构正确，index.html应在项目根目录")
        print(f"当前目录: {os.getcwd()}")
        input("按回车键退出...")
        sys.exit(1)
    
    try:
        # 查找可用端口
        port = find_available_port(preferred_port)
        if port != preferred_port:
            print(f"⚠️  端口 {preferred_port} 不可用，使用端口 {port}")
        
        # 创建服务器
        with socketserver.TCPServer(("", port), FuniHTTPRequestHandler) as httpd:
            # 打印启动信息
            print_banner(port, os.getcwd())
            
            # 延迟打开浏览器
            url = f"http://localhost:{port}"
            open_browser_delayed(url)
            
            print("\n⏳ 服务器运行中... (按 Ctrl+C 停止)\n")
            
            # 启动服务器
            httpd.serve_forever()
            
    except OSError as e:
        print(f"❌ 启动服务器时出错: {e}")
        print("\n💡 可能的解决方案:")
        print("  1. 尝试使用其他端口号")
        print("  2. 检查防火墙设置")
        print("  3. 确保没有其他程序占用端口")
        input("\n按回车键退出...")
        sys.exit(1)
    except Exception as e:
        print(f"❌ 未知错误: {e}")
        input("\n按回车键退出...")
        sys.exit(1)

if __name__ == "__main__":
    main()
